#pragma once

#include <iostream>
#include <cstdio>
#include <cerrno>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const std::string comm_path = "./myfifo";
#define DefaultFd -1 
#define Creater 1 //创建者
#define User 2 //使用者
#define Read O_RDONLY//打开方式
#define Write O_WRONLY//打开方式
#define BaseSize 4096

class NamePiped
{
private:
    //打开管道--外部传读或者写方式，我不想让你看见，设置为Private
    bool OpenNamedPipe(int mode)
    {
        _fd = open(_fifo_path.c_str(), mode);
        if (_fd < 0)  return false;
        return true;
    }

public:
    NamePiped(const std::string &path, int who)
        : _fifo_path(path), _id(who), _fd(DefaultFd)
    {
        //creater才需要创建包括后面的析构来进行管理
        if (_id == Creater)
        {
            int res = mkfifo(_fifo_path.c_str(), 0666);
            if (res != 0)//创建失败
            {
                perror("mkfifo");
            }
            std::cout << "creater create named pipe" << std::endl;//创建成功 返回值是0
        }
    }
    bool OpenForRead()
    {
        return OpenNamedPipe(Read);
    }
    bool OpenForWrite()
    {
        return OpenNamedPipe(Write);
    }
    // const &: const std::string &XXX 输入参数
    // *      : std::string * 输出型参数
    // &      : std::string &  输入输出型
    //读管道
    int ReadNamedPipe(std::string *out)
    {
        char buffer[BaseSize];
        int n = read(_fd, buffer, sizeof(buffer));
        //读取成功
        if(n > 0)
        {
            buffer[n] = 0;//牢记这个写法哇哇哇哇
            *out = buffer;
        }
        return n;
    }
    //写管道
    int WriteNamedPipe(const std::string &in)
    {
        return write(_fd, in.c_str(), in.size());
    }
    ~NamePiped()
    {
        if (_id == Creater)
        {
            int res = unlink(_fifo_path.c_str());//移除管道文件
            if (res != 0)
            {
                perror("unlink");//移除失败
            }
            std::cout << "creater free named pipe" << std::endl;
        }
        if(_fd != DefaultFd) close(_fd);//客户端服务器都可以关，无论读写方式打开
    }

private:
    const std::string _fifo_path;//路径
    int _id;//身份-creater/user
    int _fd;//文件描述符
};